package com.specdot.kraster.core;

import com.specdot.kraster.math.Vector4;

public class Rasterizer {
	protected RenderJob currentJob;

	public void render(RenderJob job) {
		currentJob = job;

		VertexShader vShader = job.vertexShader;
		Mesh meshData = job.meshData;
		int[] indices = meshData.indices;

		int indicesLength = job.meshData.indices.length;
		for (int idx = 0; idx < indicesLength;) {
			VertexOutput vo0 = vShader.invoke(buildVertexInput(meshData, indices[idx++]));
			VertexOutput vo1 = vShader.invoke(buildVertexInput(meshData, indices[idx++]));
			VertexOutput vo2 = vShader.invoke(buildVertexInput(meshData, indices[idx++]));
			
			drawTriangleWireframe(vo0, vo1, vo2);
		}
	}

	protected VertexInput buildVertexInput(Mesh meshData, int idx) {
		VertexInput vin = new VertexInput();
		vin.pos = meshData.positions[idx];
		
		if (meshData.colors != null)
			vin.color = meshData.colors[idx];

		return vin;
	}

	protected void clipSpaceToScreenSpace(Vector4 v) {
		v.x /= v.w;
		v.y /= v.w;
		v.z /= v.w;

		v.x = v.x * 0.5f + 0.5f;
		v.y = v.y * 0.5f + 0.5f;
		v.z = v.z * 0.5f + 0.5f;
	}

	protected void drawTriangleWireframe(VertexOutput vo0, VertexOutput vo1, VertexOutput vo2) {
		Vector4 v0 = vo0.pos;
		Vector4 v1 = vo1.pos;
		Vector4 v2 = vo2.pos;

		clipSpaceToScreenSpace(v0);
		clipSpaceToScreenSpace(v1);
		clipSpaceToScreenSpace(v2);
		
		Screen screen = currentJob.targetScreen;
		
		screen.drawLineUV(v0.x, v0.y, v1.x, v1.y, 1f, 0, 0, 1);
		screen.drawLineUV(v1.x, v1.y, v2.x, v2.y, 1f, 0, 0, 1);
		screen.drawLineUV(v2.x, v2.y, v0.x, v0.y, 1f, 0, 0, 1);
	}
}
